﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MultiAnnotatedRegex.machine;
using MultiAnnotatedRegex.tree;

namespace MultiAnnotatedRegex.compiler {
	class Compiler<Tag> : TreeVisitor {
		CompoundMachine<Tag> currentParent;

		public Machine<Tag> Compile(Tree ast) {
			ConcatMachine<Tag> result = new ConcatMachine<Tag>();
			currentParent = result;
			Visit(ast);
			return result;
		}

		public override void VisitLiteral(LiteralTree literalTree) {
			currentParent.Append(new LiteralMachine<Tag>(literalTree.Literal));
		}

		public override void VisitConcat(ConcatTree concatTree) {
			var result = new ConcatMachine<Tag>();
			currentParent.Append(result);

			var oldParent = currentParent;
			currentParent = result;
			base.VisitConcat(concatTree);
			currentParent = oldParent;
		}

		public override void VisitOneOf(OneOfTree oneOfTree) {
			var result = new OneOfMachine<Tag>();
			currentParent.Append(result);

			var oldParent = currentParent;
			currentParent = result;
			base.VisitOneOf(oneOfTree);
			currentParent = oldParent;
		}

		public override void VisitRepetition(RepetitionTree repetitionTree) {
			var result = new RepetitionMachine<Tag>() { Min = repetitionTree.Min, Max = repetitionTree.Max };
			currentParent.Append(result);

			var oldParent = currentParent;
			currentParent = result;
			base.VisitRepetition(repetitionTree);
			currentParent = oldParent;
		}

		public override void VisitAnyTree(tree.premade.AnyTree anyTree) {
			currentParent.Append(new AnyMachine<Tag>());
		}

		public override void VisitCharacterClass(tree.premade.CharacterClassTree characterClassTree) {
			currentParent.Append(new CharacterClassMachine<Tag>(characterClassTree.Class));
		}

	}
}
